#pragma once

#include <time.h>
#include <stdint.h>
#include "BufMgr.h"
#include "PkgBuf.h"
#include "Protocol.h"

class CIodp;
class CWorkSvr;

enum class DataState : uint8_t
{
    TypeParse,
    ModuleParse,
    DataParse
};

class CClient
{
public:
    CClient();
    virtual ~CClient();

public:
    bool Init(int ifd, CWorkSvr *pSvr, SSL_CTX *ctxSvr, CBufMgr<> *pBufMgr);
    void Destroy();

    // 接收数据到pBuf
    int Recv();

    // 读取m_pRecvBuf中的数据
    int Read(void *pDest, int iLen);

    // socket可写时发送m_bufSend中已有数据
    int Send();

    // m_bufSend中无数据时发送外部数据，没发送完则缓冲到m_bufSend
    // pSrc为已根据协议组包的数据，仅限主线程使用
    int SendPackage(void *pSrc, int iLen);

    // 模块数据处理完成时调用，pSrc为纯数据，需根据协议组包发送，仅限主线程使用
    int SendData(void *pSrc, int iLen);

    // pSrc为纯数据，需根据协议组包发送(IPC协议头，Protocol类协议)，非主线程使用
    bool IpcSendDataExt(void *pSvr, CClient *pClnt, void *pSrc, int iLen);

    // 发送数据给其它客户端实例内部处理，不发送到终端
    bool IpcSendDataInt(void *pSvr, CClient *pClnt, void *pSrc, int iLen);

    // 数据处理
    HandleResult DataHandle();

    // IPC数据处理,对其它客户端实例通过IPC发送过来的数据进行内部处理，不外发
    // 数据需快速处理，耗时长的处理，需给到其它线程处理
    bool IpcDataHandle(void *pSrc, int iLen);

public:
    int GetSocket() { return m_ifd; }
    bool HasSendData() { return ((nullptr != m_pSendBuf) ? (m_pSendBuf->GetDataLength() > 0) : false); }
    bool HasRecvData() { return ((nullptr != m_pRecvBuf) ? (m_pRecvBuf->GetDataLength() > 0) : false); }

public:
    ProtType GetProtType() { return m_eProt; }
    void SetProtType(ProtType pt) { m_eProt = pt; }

    int8_t GetModule() { return m_iMod; }
    void SetModule(int8_t iMod) { m_iMod = iMod; }

private:
    int HandShake();
    HandleResult ProtTypeParse();
    HandleResult ModuleParse();
    HandleResult DataProcess();
    CIodp *GetIodp(int8_t iMod);

private:
    int m_ifd;        // socket描述符
    ProtType m_eProt; // 协议类型
    int8_t m_iMod;    // 归属模块
    bool m_bShake;    // SSL连接时，是否已完成握手
    DataState m_ds;   // 数据处理状态

    SSL *m_pssl;           // ssl
    CWorkSvr *m_pSvr;      // 客户端所在服务
    CProtocol *m_pProt;    // 数据传输协议
    PkgBuf *m_pbRecv;      // 接收协议解析后的缓冲数据包
    CBuffer<> *m_pRecvBuf; // 接收缓冲
    CBuffer<> *m_pSendBuf; // 发送缓冲
    CIodp *m_pIodp;        // 数据业务处理
    void *m_pClntInfo;     // 客户端信息
    time_t m_tLast;        // 最后一次输入时间
};
